﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;

namespace AsyncNetworkTransferClient
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private Socket client;
        private byte[] data = new byte[1024];
        private int size = 1024;
        private ListBox results;
        FileStream stream;
        private void button1_Click(object sender, EventArgs e)
        {
            textBox2.Text += "Connecting...";
            Socket newsock = new Socket(AddressFamily.InterNetwork,
                       SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint iep = new IPEndPoint(IPAddress.Parse(txtIP.Text), 9050);
            newsock.BeginConnect(iep, new AsyncCallback(Connected), newsock);
        }
        private delegate void AddTextDelegate(object item);
        private void AddText(object item)
        {
            if (this.textBox2.InvokeRequired)
            {
                this.textBox2.Invoke(new AddTextDelegate(this.AddText), item);
            }
            else
            {
                this.textBox2.Text += item.ToString() + Environment.NewLine;
            }
        }
        void Connected(IAsyncResult iar)
        {
            client = (Socket)iar.AsyncState;
            try
            {
                client.EndConnect(iar);
                AddText("Connected to: " + client.RemoteEndPoint.ToString());
                client.BeginReceive(data, 0, size, SocketFlags.None,
                       new AsyncCallback(ReceiveData), client);
            }
            catch (SocketException)
            {
                //textBox2.Text += "Error connecting";
            }
        }
        void ReceiveData(IAsyncResult iar)
        {
            Socket remote = (Socket)iar.AsyncState;
            int recv = remote.EndReceive(iar);
            string stringData = Encoding.ASCII.GetString(data, 0, recv);
            data = new byte[1024];
            AddText(stringData);
            if (stringData == "Message")
            {
                remote.BeginReceive(data, 0, size, SocketFlags.None,
                   new AsyncCallback(ReceiveMessageData), remote);
            }
            else
            if (stringData == "File")
            {
                remote.BeginReceive(data, 0, size, SocketFlags.None,
                   new AsyncCallback(ReceiveFile), remote);
            }
            else
            remote.BeginReceive(data, 0, size, SocketFlags.None,
                   new AsyncCallback(ReceiveData), remote);
        }

        void ReceiveMessageData(IAsyncResult iar)
        {
            Socket remote = (Socket)iar.AsyncState;
            int recv = remote.EndReceive(iar);
            string stringData = Encoding.ASCII.GetString(data, 0, recv);
            data = new byte[1024];
            AddText(stringData);
            remote.BeginReceive(data, 0, size, SocketFlags.None,
                   new AsyncCallback(ReceiveData), remote);
        }
        void ReceiveFile(IAsyncResult iar)
        {
            Socket remote = (Socket)iar.AsyncState;
            int recv = remote.EndReceive(iar);
            string stringData = Encoding.ASCII.GetString(data, 0, recv);
            data = new byte[1024];
            AddText(stringData);
            stream = File.Create(@"C:\" + stringData);
            remote.BeginReceive(data, 0, size, SocketFlags.None,
                   new AsyncCallback(ReceiveFileLength), remote);
        }
        int fileLength = 0;
        int currentFileRecv = 0;
        void ReceiveFileLength(IAsyncResult iar)
        {
            Socket remote = (Socket)iar.AsyncState;
            int recv = remote.EndReceive(iar);
            string stringData = Encoding.ASCII.GetString(data, 0, recv);
            data = new byte[1024];
            AddText(stringData);
            fileLength = int.Parse(stringData);
            currentFileRecv = 0;
            remote.BeginReceive(data, 0, size, SocketFlags.None,
                   new AsyncCallback(ReceiveFileData), remote);
        }
        void ReceiveFileData(IAsyncResult iar)
        {
            Socket remote = (Socket)iar.AsyncState;
            int recv = remote.EndReceive(iar);
            string stringData = Encoding.ASCII.GetString(data, 0, recv);
            data = new byte[1024];
            currentFileRecv += 1024;
            AddText(stringData);
            stream.Write(data, 0, recv);
            if (currentFileRecv >= fileLength)
            {
                stream.Close();
                remote.BeginReceive(data, 0, size, SocketFlags.None,
                   new AsyncCallback(ReceiveData), remote);
            }
            else
                remote.BeginReceive(data, 0, size, SocketFlags.None,
                    new AsyncCallback(ReceiveFileData), remote);
        }

        void SendData(IAsyncResult iar)
        {
            Socket remote = (Socket)iar.AsyncState;
            int sent = remote.EndSend(iar);
            remote.BeginReceive(data, 0, size, SocketFlags.None,
                   new AsyncCallback(ReceiveData), remote);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
        }

        private void button2_Click(object sender, EventArgs e)
        {
            byte[] message = Encoding.ASCII.GetBytes(textBox3.Text + " : " + textBox1.Text);
            textBox1.Clear();
            client.BeginSend(message, 0, message.Length, SocketFlags.None,
                   new AsyncCallback(SendData), client);

        }

    }
}
